package com.yuandian.ops.workbench.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.api.management.entity.ConfBusiness;
import com.yuandian.api.management.feign.RemoteBusinessService;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.ops.workbench.enums.AlarmIndicatorCodeEnum;
import com.yuandian.ops.workbench.mapper.DevOpsHomePageMapper;
import com.yuandian.ops.workbench.po.AlarmListParams;
import com.yuandian.ops.workbench.service.IDevOpsHomePageService;
import com.yuandian.ops.workbench.vo.*;
import com.yuandian.utils.PageDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 说明：业务数据统计service实现
 * @Author LinShiHe
 * @Date 2021/07/02
 */
@Service
@Slf4j
public class DevOpsHomePageServiceImpl implements IDevOpsHomePageService {

	@Autowired
	private DevOpsHomePageMapper healthRateTopMapper;

	@Autowired
	private RemoteBusinessService remoteBusinessService;


	/**
	 * 查询监控概况
	 * @return 监控概况vo对象
	 */
	@Override
	public MonitorOverviewVo queryRecentMonitorOverview(AlarmListParams params) {
		MonitorOverviewVo monitorOverviewVo = healthRateTopMapper.queryRecentMonitorOverview(params);

		if (monitorOverviewVo == null) {
			// 查询无该天数据，设置默认值
			monitorOverviewVo = new MonitorOverviewVo();
			monitorOverviewVo.setSystemTotal(0);
			monitorOverviewVo.setSystemUnhealthTotal(0);
			monitorOverviewVo.setSegmentTotal(0);
			monitorOverviewVo.setSegmentUnhealthTotal(0);
			monitorOverviewVo.setBusinessTotal(0);
			monitorOverviewVo.setBusinessUnhealthTotal(0);
			monitorOverviewVo.setBusinessVisitTotal(0);
			monitorOverviewVo.setBusinessVisitUnhealthTotal(0);
			monitorOverviewVo.setUserTotal(0);
		}

		return monitorOverviewVo;
	}


	/**
	 * 查询区域业务统计（地图）
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用返回对象
	 */
	@Override
	public R<Object> queryMapAreaBusinessStatistics(AlarmListParams params) {
 		// list中只取没各区域的第一条数据，map用于判断是否已经取了某区域的
		Map<String, String> map = new HashMap<>();
		List<AreaBusinessStatisticsVo> resList = new ArrayList<>();
		List<AreaBusinessStatisticsVo> list = healthRateTopMapper.queryMapAreaBusinessStatistics(params);
		if (list != null && list.size() > 0) {
			for (AreaBusinessStatisticsVo res : list) {
				if (!map.containsKey(res.getAreaName())) {
					resList.add(res);
					map.put(res.getAreaName(), res.getHealthRate());
				}
			}
		}
		return R.ok(resList);
	}

	/**
	 * 查询区域业务统计
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用返回对象
	 */
	@Override
	public R<Object> queryAreaBusinessStatistics(AlarmListParams params) {

		return  R.ok(healthRateTopMapper.queryAreaBusinessStatistics(params));
	}

	/**
	 * 根据开始时间、结束时间、时间间隔 自动生成X轴数据
	 * @param starTime
	 * @param endTime
	 * @param timeInterval 时间间隔
	 * @return
	 */
	public static List<String> getTimeListByJDK8(String starTime, String endTime, int timeInterval) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime startDateTime = LocalDateTime.parse(starTime, formatter);
		LocalDateTime endDateTime = LocalDateTime.parse(endTime, formatter);
		List<String> timeList = new ArrayList<>();

		//遍历从startTime 到 endTime 时间间隔的所有时间点
		while (startDateTime.isBefore(endDateTime)){
			timeList.add(startDateTime.format(formatter));
			startDateTime = startDateTime.plusMinutes(timeInterval);
		}
		return timeList;
	}


	/**
	 * 查询系统受理量、告警量趋势
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用返回对象
	 */
	@Override
	public R queryCompleteAlarmTrend(AlarmListParams params) {

		// 获取完整的时间刻度列表(主要要去除最后一个时间点, 因为SQL条件是: < endTime)
		List<String> timeList =  getTimeListByJDK8(params.getStartTime(), params.getEndTime(), 1);

		// 执行查询（今日）
		List<CompleteAlarmTrendVo> todayList = healthRateTopMapper.queryCompleteAlarmTrend(params);

		// 设置表名(昨日)
		String beforeStartTime = DateUtil.formatDateTime(DateUtil.offsetDay(DateUtil.parse(params.getStartTime()), -1));
		String beforeEndTime = DateUtil.formatDateTime(DateUtil.offsetDay(DateUtil.parse(params.getEndTime()), -1));


		params.setStartTime(beforeStartTime);
		params.setEndTime(beforeEndTime);
		// 执行查询（昨日）
		List<CompleteAlarmTrendVo> yesterdayList = healthRateTopMapper.queryCompleteAlarmTrend(params);
		List<CompleteAlarmTrendVo> list = new ArrayList<>();
		// 合并数据
		Map<String, CompleteAlarmTrendVo> yesterdaycollect = yesterdayList.stream().collect(Collectors.toMap(CompleteAlarmTrendVo::getCycleTime, v -> v, (k1, k2) -> k1));
		Map<String, CompleteAlarmTrendVo> todaycollect = todayList.stream().collect(Collectors.toMap(CompleteAlarmTrendVo::getCycleTime, v -> v, (k1, k2) -> k1));

		List<CompleteAlarmTrendVo> resList = new ArrayList<>();
		for (String s : timeList) {
			CompleteAlarmTrendVo vo = new CompleteAlarmTrendVo();
			// 回填今日访问量和告警量
			if (todaycollect.containsKey(s)) {
				vo.setVisitCount(todaycollect.get(s).getVisitCount());
				vo.setAlarmCount(todaycollect.get(s).getAlarmCount());
			}else {
				vo.setVisitCount(0);
				vo.setAlarmCount(0);
			}
			// 回填昨日访问量
			String yesterdayCycleTime = DateUtil.formatDateTime(DateUtil.offsetDay(DateUtil.parse(s), -1));
			if (yesterdaycollect.containsKey(yesterdayCycleTime)) {
				vo.setYesterdayCount(yesterdaycollect.get(yesterdayCycleTime).getVisitCount());
			}else {
				vo.setYesterdayCount(0);
			}
			vo.setCycleTime(s);
			vo.setSystemId(params.getSystemId());
			resList.add(vo);
		}

		return  R.ok(resList);
	}


	/**
	 * 查询业务告警TOP5
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用分页对象
	 */
	@Override
	public R<Object> getBusinessBusiAlarmTop(AlarmListParams params) {

		List<BusinessAlarmTopVo> resList = new ArrayList<>();
		// 查询健康度
		List<BusinessAlarmTopVo> healthList = healthRateTopMapper.getBusinessListHealth(params);
		// 查询告警
		List<BusinessAlarmTopVo> AlarmList = healthRateTopMapper.getBusinessListAlarm(params);
		if (healthList.size() > 0) {
			for (BusinessAlarmTopVo alarmTopVo : AlarmList) {
				for (BusinessAlarmTopVo healthVO : healthList) {
					if (healthVO.getSystemId().equals(alarmTopVo.getSystemId())
							&& healthVO.getBusinessCode().equals(alarmTopVo.getBusinessCode())) {
						alarmTopVo.setHealthRate(healthVO.getHealthRate());
						resList.add(alarmTopVo);
						break;
					}
				}
			}
		}
		if (resList.size() > 5) {
			return R.ok(resList.subList(0, 5));
		}
		return R.ok(resList);
	}

	/**
	 * 查询业务健康度TOP5
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用分页对象
	 */
	@Override
	public R<Object> getBusinessHealthTop(AlarmListParams params) {
		List<BusinessAlarmTopVo> resList = new ArrayList<>();
		// 查询健康度
		List<BusinessAlarmTopVo> healthList = healthRateTopMapper.getBusinessListHealth(params);
		// 查询告警
		List<BusinessAlarmTopVo> AlarmList = healthRateTopMapper.getBusinessListAlarm(params);
		if (!CollectionUtils.isEmpty(healthList)) {
			for (BusinessAlarmTopVo healthVO : healthList) {
				for (BusinessAlarmTopVo alarmTopVo : AlarmList) {
					if (healthVO.getSystemId().equals(alarmTopVo.getSystemId())
							&& healthVO.getBusinessCode().equals(alarmTopVo.getBusinessCode())) {
						healthVO.setAlarmNum(alarmTopVo.getAlarmNum());
						resList.add(healthVO);
						break;
					}
				}
			}
		}
		List<BusinessAlarmTopVo> keyList = new ArrayList<>();
		// 过滤不属于 关键业务 的数据
		keyList = getKeyBusinessList(resList);

		if (keyList.size() > 5) {
			return R.ok(keyList.subList(0, 5));
		}

		return R.ok(keyList);
	}

	/**
	 * 获取关键业务
	 * @param list
	 * @return
	 */
	private List<BusinessAlarmTopVo> getKeyBusinessList(List<BusinessAlarmTopVo> list) {
		List<BusinessAlarmTopVo> resList = new ArrayList<>();

		Optional<R<List<ConfBusiness>>> result = Optional.empty();
		try {
			long sTime = System.currentTimeMillis();
			result = Optional.of(remoteBusinessService.queryKeyBusiness());
			log.info("[运维工作台]-[远程调用-后台配置服务]-[获取关键业务列表]-耗时: {} MS", System.currentTimeMillis() - sTime);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("[运维工作台]-[远程调用-后台配置服务]-[获取关键业务列表]报错: {}" + e.getMessage());
		}

		Map<String, String> map = result.map(R::getData)
				.orElse(Collections.emptyList())
				.stream()
				.collect(Collectors.toMap(ConfBusiness::getBusinessCode,
						ConfBusiness::getName));

		resList = list.stream()
				.filter(businessAlarmTopVo -> StringUtils.isNotEmpty(map.get(businessAlarmTopVo.getBusinessCode())))
				.collect(Collectors.toList());

//		return resList;	TODO 目前配置表尚未配置关键业务，后续配置了需要放开该注释
		return list;
	}

	/**
	 * (BPM 4.0)
	 * 查询最新健康度告警 topN
	 * @param params 查询业务告警信息相关数据请求对象
	 * @return 通用分页对象
	 */
	@Override
	public PageDataInfo queryRecentHealthRateAlarmTopN(AlarmListParams params) {
		Page<RecentHealthRateTopVo> page = new Page<>(params.getPageNum(), params.getPageSize());
		List<RecentHealthRateTopVo> list = healthRateTopMapper.getSysHealthRateTop(page, params);
		if (!CollectionUtils.isEmpty(list)) {
			// 重list中获取主键ID列表然后去查询'健康度低'最新告警周期的数据 (新增此处逻辑是受限于 Doris 不能子查询)
			List<String> idList = list.stream().map(RecentHealthRateTopVo::getId).collect(Collectors.toList());
			List<RecentHealthRateTopVo> childList = healthRateTopMapper.getNewestSysHealthRateTop(idList);
			Map<String, RecentHealthRateTopVo> resMap = new HashMap<>();
			resMap = childList.stream().collect(Collectors.toMap(RecentHealthRateTopVo::getId, o -> o, (key1, key2) -> key2));
			// 回填最新的健康度和失败率
			for (RecentHealthRateTopVo vo : list) {
				RecentHealthRateTopVo childVo = resMap.get(vo.getId());
				if (childVo != null) {
					vo.setNewestFailRate(childVo.getNewestFailRate());
					vo.setNewestHealthRate(childVo.getNewestHealthRate());
					vo.setCycleTime(childVo.getCycleTime());
					vo.setStartTime(childVo.getStartTime());
					vo.setEndTime(childVo.getEndTime());
					vo.setAlarmIndicatorCode(AlarmIndicatorCodeEnum.healthy.getIndicatorType());
				}
			}
		}

		return new PageDataInfo(page, list);
	}


}
